<?php
/**
 * Created by PhpStorm.
 * User: daimin
 * Date: 15/7/22
 * Time: 下午6:31
 */

namespace common\services\common;

use common\support\DateTimeHelper;
use common\services\BaseService;
use common\entities\common\MyscrmApplicationEntity;
use common\entities\common\MyscrmFunctionupgradeEntity;
use common\entities\common\MyscrmOrganizationToAuthorizeEntity;
use common\entities\common\MyscrmOrganizationToPackageEntity;
use common\entities\common\MyscrmPackageEntity;
use common\entities\common\MyscrmPackageToApplicationEntity;
use common\entities\common\MyscrmContractEntity;
use common\repositories\common\MyscrmAuthorizeRepository;
use common\repositories\common\MyscrmContractRepository;
use common\repositories\common\MyscrmApplicationRepository;
use common\repositories\common\MyscrmFunctionupgradeRepository;
use common\repositories\common\MyscrmOrganizationRepository;
use common\repositories\common\MyscrmPackageRepository;
use yii\helpers\ArrayHelper;

/**
 * 合同处理接口类
 * Class MyscrmContractService
 * @package common\services\common
 */
class MyscrmContractService extends BaseService {

    private $_packageRepository = null;
    private $_organizationRepository = null;
    private $_myscrmApplicationRepository;
    private $_contractRepository;
    private $_myscrmAuthorizeRepository;
    private $_myscrmFunctionupgradeRepository;

    public function __construct(MyscrmPackageRepository $packageRepository,
                                MyscrmOrganizationRepository $organizationRepository,
                                MyscrmApplicationRepository $myscrmApplicationRepository,
                                MyscrmContractRepository $contractRepository,
                                MyscrmAuthorizeRepository $myscrmAuthorizeRepository,
                                MyscrmFunctionupgradeRepository $myscrmFunctionupgradeRepository
    ){
        $this->_packageRepository = $packageRepository;
        $this->_organizationRepository = $organizationRepository;
        $this->_myscrmApplicationRepository = $myscrmApplicationRepository;
        $this->_contractRepository = $contractRepository;
        $this->_myscrmAuthorizeRepository = $myscrmAuthorizeRepository;
        $this->_myscrmFunctionupgradeRepository = $myscrmFunctionupgradeRepository;
        parent::__construct();
    }

    /**
     * 添加合同，新增授权
     * @param $contractInfo
     * @return bool
     * @throws \Exception
     */
    public function saveContractAuth($contractInfo){

        if(empty($contractInfo)){
            throw new \Exception("合同信息不能为空");
        }

        // 检查必要的值
        if(!array_key_exists('contract_num', $contractInfo) || !array_key_exists('party_a', $contractInfo) ||
           !array_key_exists('contract_type', $contractInfo) || !array_key_exists('begin_on', $contractInfo) ||
           !array_key_exists('end_on', $contractInfo) || !array_key_exists('organization_id', $contractInfo) ||
           !array_key_exists('auth_info', $contractInfo)){
            throw new \Exception("缺少参数");
        }

        //验证auth_info必须是数组
        if(!is_array(ArrayHelper::getValue($contractInfo, 'auth_info'))){
            throw new \Exception("auth_info必须是数组");
        }




        // 查询指定的organization_id是否存在
        $organizationId = ArrayHelper::getValue($contractInfo, 'organization_id');
        $orgObj = $this->_organizationRepository->getById($organizationId);
        if(empty($orgObj)){
            throw new \Exception("不存在的租户信息");
        }

        // 检查合同号是否存在, 存在就是提示错误
        $contractNum = ArrayHelper::getValue($contractInfo, 'contract_num');
        $contractObj = $this->_contractRepository->getContractByContractNum($contractNum, $organizationId);

        // 检查购买类型，如果已经商户已存在授权就是增购，否则就是新增
        $orgContractCount = intval($this->_contractRepository->getContractByOrganizationId($organizationId));
        $contractType = intval(ArrayHelper::getValue($contractInfo, 'contract_type'));
        if($orgContractCount > 0){
            //已存在该商户的合同，那么之后的合同都是增购的了
            if($contractType == 1 && empty($contractObj)){ //如果新增而合同是update，那么不提示
                throw new \Exception("购买类型不对，应该为增购");
            }
        }else{
            if($contractType == 2){
                throw new \Exception("购买类型不对，应该为新增");
            }
        }
        // 验证日期格式
        if(!DateTimeHelper::validateDate(ArrayHelper::getValue($contractInfo, 'begin_on')) || !DateTimeHelper::validateDate(ArrayHelper::getValue($contractInfo, 'end_on'))){
            throw new \Exception("租期，时间格式不对");
        }
        // 租期，结束时间不能小于开始时间
        if(strtotime(ArrayHelper::getValue($contractInfo, 'begin_on')) > strtotime(ArrayHelper::getValue($contractInfo, 'end_on'))){
            throw new \Exception("租期，结束时间不能小于开始时间");
        }

        // 授权授不能小于已用授权数(需要从auth_info中获取)
        $authInfo =  ArrayHelper::getValue($contractInfo, 'auth_info');
        if(!empty($authInfo) && is_array($authInfo)){
            foreach($authInfo as $aInfo){
                if(intval(ArrayHelper::getValue($aInfo, 'total_num')) < intval(ArrayHelper::getValue($aInfo, 'used_num'))){
                    throw new \Exception("授权数不能小于已用授权数");
                }
            }
        }

        //保存合同，开启事务
        $connection = MyscrmContractEntity::getDb();
        $transaction = $connection->beginTransaction();
        try{
            $contractId = $this->_contractRepository->saveContract($contractInfo);
            foreach($authInfo as $aInfo){
                $this->_myscrmAuthorizeRepository->saveOrganizationToAuthorize($organizationId, $contractId, $aInfo);
            }
            $transaction->commit();
            return true;
        }catch(\Exception $ex){
            $transaction->rollBack();
            throw new \Exception($ex->getMessage());
        }

    }

    /**
     * 通过租户ID，拿到其合同列表
     * @param $orgId
     * @return array
     * @throws \Exception
     */
    public function getContractsByOrgId($orgId){

        if(empty($orgId)){
            throw new \Exception("租户ID不能为空");
        }
        $contracts = $this->_contractRepository->getContractByOrganizationId($orgId);
        return $contracts;
    }

    /**
     * 根据合同号获取合同详情
     * @param $contractId
     * @return null|static
     * @throws \Exception
     */
    public function getContractById($contractId){
        if(empty($contractId)){
            throw new \Exception("合同ID不能为空");
        }

        return $contract = $this->_contractRepository->getContractById($contractId);
    }

    /**
     * 作废合同
     */
    public function cancelContract($orgName, $contractId){
        if(empty($orgName)){
            throw new \Exception("租户企业号不能为空");
        }

        if(empty($contractId)){
            throw new \Exception("租户合同ID不能为空");
        }

        $orgId = $this->_organizationRepository->getOrgId($orgName);
        if(empty($orgId)){
            throw new \Exception("租户不存在");
        }

        $contractObj = $this->_contractRepository->getContractById($contractId);
        if(empty($contractObj)){
            throw new \Exception("租户合同不存在");
        }

        $this->_contractRepository->updateStatus($orgId, $contractId, 2);  //作废
    }

    /**
     * 根据租户名称拿到合同列表，包括授权信息
     * @param $orgName
     * @return array
     * @see formatContractList
     */
    public function getContractsList($orgName){
        $orgId = $this->_organizationRepository->getOrgId($orgName);
        $contractList = $this->_contractRepository->getContractByOrganizationId($orgId);
        $applicationList = $this->_myscrmApplicationRepository->getAll();
        $authList = $this->_myscrmAuthorizeRepository->getAuthorizeListByOrgId($orgId);
        $authUsedList = $this->_myscrmAuthorizeRepository->getUsedAuthorizeNum($orgName);
        return $this->formatContractList($contractList,$applicationList,$authList, $authUsedList);

    }

    /**
     * 通过租户企业号和合同ID获取合同详情
     * @param $orgName 租户名称
     * @param $contractId
     * @return array
     * @throws \Exception
     */
    public function getContractDetailById($orgName, $contractId){
        if(empty($orgName)){
            throw new \Exception("租户企业号不能为空");
        }

        $orgId = $this->_organizationRepository->getOrgId($orgName);

        if(empty($orgId)){
            throw new \Exception("不存在的租户");
        }

        if(empty($contractId)){
            throw new \Exception("合同ID不能为空");
        }

        return $this->_contractRepository->getContractDetailById($orgId, $contractId);
    }

    /**
     * @param $contractList \common\entities\common\MyscrmContractEntity[]
     * @param $applicationList \common\entities\common\MyscrmApplicationEntity[]
     * @param $authList \common\entities\common\MyscrmOrganizationToAuthorizeEntity[]
     * @param $authUsedList array [[AuthorizeId=>count],...]
     * @return array ['nums' =>['total_num' => $totalCount, 'used_num' => $totalUsedCunt],
     * 'contracts' => $contracts]
     */
    private function formatContractList($contractList, $applicationList, $authList, $authUsedList)
    {
        $totalCount = 0;
        $totalUsedCunt = 0;

        //格式化每个应用的数据,并按合同Id分组
        /** @var \common\entities\common\MyscrmApplicationEntity[] $applicationIndexById */
        $applicationIndexById = ArrayHelper::index($applicationList,'ApplicationId');
        $authIndexByContractId = [];
        foreach($authList as $auth){
            $authUsedCount = isset($authUsedList[$auth->Id]) ? $authUsedList[$auth->Id] : 0;
            $authArray = [
                'id' => $auth->ApplicationId,
                'friendly_name' => $applicationIndexById[$auth->ApplicationId]->FriendlyName,
                'unique_name' => $applicationIndexById[$auth->ApplicationId]->UniqueName,
                'total_num' => $auth->TotalNum,
                'used_num' => $authUsedCount,
            ];
            $authIndexByContractId[$auth->ContractId][] = $authArray;

            $totalCount += $auth->TotalNum;
            $totalUsedCunt += $authUsedCount;
        }

        $contracts = [];

        foreach($contractList as $contract){
            $contractArray = $contract->toArray();
            $contractArray['packages'] = isset($authIndexByContractId[$contract->ContractId]) ? $authIndexByContractId[$contract->ContractId] : [];
            $contracts[] = $contractArray;
        }

        return ['nums' =>['total_num' => $totalCount, 'used_num' => $totalUsedCunt],
                'contracts' => $contracts];
    }

}
